package com.sais.manage.boot.platform.config;

import com.sais.common.constant.CommonString;
import com.sais.common.utils.RsaUtils;
import com.sais.manage.boot.platform.dto.UserLoginDTO;
import com.sais.manage.boot.platform.entity.Rsa;
import com.sais.manage.boot.platform.mapper.PermissionMapper;
import com.sais.manage.boot.platform.mapper.RsaMapper;
import com.sais.manage.boot.platform.mapper.UserMapper;
import com.sais.manage.boot.platform.utils.EncryptionUtils;
import com.sais.manage.boot.platform.utils.ShiroUtils;
import lombok.SneakyThrows;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * <p>
 * 授权验证
 * </p>
 *
 * @author zwp
 * @since 2019-10-10
 **/
@Component
public class ShiroUserRealm extends AuthorizingRealm {


    public static Map<String, Session> LOGIN_SESSION_ID = new HashMap<>();

    @Resource
    UserMapper userMapper;

    @Resource
    PermissionMapper permissionMapper;

    @Resource
    private RsaMapper rsaMapper;

    /**
     * 授权(验证权限时调用)
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        Set<String> strings = new HashSet<>(32);
        strings.add("platform:session:list");
        strings.add("platform:user:update:password");
        UserLoginDTO loginUser = ShiroUtils.getLoginUser();
        //管理员添加所有权限
        if (CommonString.ADMIN.equals(loginUser.getAccount())) {
            List<String> vals = permissionMapper.listAllPermissionVal();
            strings.addAll(vals);
        }
        Set<String> permissions = permissionMapper.listPermissionValByUserId(loginUser.getUkId());
        strings.addAll(permissions);
        info.setStringPermissions(strings);
        return info;
    }

    /**
     * 认证(登录时调用)
     */
    @SneakyThrows
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String account = (String) token.getPrincipal();
        String password = new String((char[]) token.getCredentials());
        //拿到私钥将加密后的密码解密
        UserLoginDTO userLoginDTO = userMapper.selectUserByAccount(account);

        if (StringUtils.isEmpty(userLoginDTO)) {
            throw new AuthenticationException("账号不存在！");
        }
        if (StringUtils.isEmpty(password)) {
            throw new AuthenticationException("密码为空!");
        }
        if (CommonString.USER_STATUS.equals(userLoginDTO.getStatus())) {
            throw new AuthenticationException("账号已锁定！联系管理员解锁！");
        }

        Rsa rsa = rsaMapper.selectById(userLoginDTO.getUkId());
        String encryption;
        try {
            //将输入的密码解密 再加密与数据库中加密的密码进行比较
            String decrypt = RsaUtils.decrypt(password, rsa.getPrivateKey());
            encryption = EncryptionUtils.encryption(decrypt, userLoginDTO.getSalt());
        } catch (Exception e) {
            throw new AuthenticationException("登录失败!");
        }

        if (!userLoginDTO.getPassword().equals(encryption)) {
            throw new AuthenticationException("账号或者密码错误!");
        }

        userLoginDTO.setPassword("");
        userLoginDTO.setSalt("");
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userLoginDTO, password, getName());
        return info;
    }

}
